import { useWebSocket as useWS } from "@vueuse/core";
import type { WatchStopHandle } from "vue";

const baseWSHref = import.meta.env.VITE_BASE_WS;

interface RespData<T = any> {
  status: boolean; // 响应结果
  key: string; // 唯一id，防止同一请求访问多次，回调结果不确定
  data?: T;
  message?: string;
}

export type Callback<T = any> = (status: boolean, data?: T) => void;

export const useWebSocket = (token: string) => {
  const callbackArr: Record<string, Callback> = {};
  let watchItem: WatchStopHandle;

  const {
    status,
    data,
    open: orignOpen,
    send: orignSend,
    close: orignClose,
  } = useWS(`${baseWSHref}/${token}`, {
    immediate: false,
    // autoReconnect: false,
    // heartbeat: {
    //   message: "ping",
    //   interval: 5000,
    // },
  });

  const open = () => {
    orignOpen();
    watchItem = watch(
      () => data.value,
      (newVal) => {
        const res: RespData = JSON.parse(newVal);
        if (!res.status) {
          window.$message.error(res.message!);
        }
        if (callbackArr[res.key]) {
          callbackArr[res.key](res.status, res.data);
          Reflect.deleteProperty(callbackArr, res.key);
        }
      },
      { immediate: true }
    );
  };

  const send = <T>(code: string, data?: any, callback?: Callback<T>) => {
    if (status.value !== "OPEN") {
      window.$message.error("未连接至服务器");
      
      callback && callback(false);
    }

    const key = crypto.randomUUID();
    const params = JSON.stringify({ code, key, data });
    orignSend(params);
    if (callback) callbackArr[key] = callback;
  };

  const close = () => {
    orignClose(1000);
    watchItem && watchItem();
  };

  return { status, data, open, send, close };
};
